﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Parallel3M.parallel3m.payload;
using System.Collections;
using System.Xml;

namespace Parallel3M.parallel3m.framework
{
    public class ParallelCycleProcessor:ParallelProcessor
    {

        //
        public PayloadGraph plGraph;
        public ParallelChannelSelector selector;
        public ParallelChannel completedChannel;        
        public ParallelChannel readyChannel;
        public ParallelChannel selectChannel;

        public ParallelCycleProcessorController controller;
        
        //
        public void ConnectChannelSelector(ParallelChannel readyChannel,ParallelChannelSelector selector,ParallelChannel completedChannel)
        {
            this.selector=selector;
            this.readyChannel = readyChannel;
            this.completedChannel = completedChannel;

            selectChannel=new ParallelChannel();

            ParallelConnection conn1 = new ParallelConnection();
            conn1.from = selector;
            conn1.to = selectChannel;
            conn1.routeTag = id;
            selector.outputConnections.Add(conn1);
            selectChannel.inputConnections.Add(conn1);

            ParallelConnection conn2 = new ParallelConnection();
            conn2.from = selectChannel;
            conn2.to = this;
            conn1.routeTag = id;
            selectChannel.outputConnections.Add(conn2);
            this.inputConnections.Add(conn2);

            ParallelConnection conn3 = new ParallelConnection();
            conn3.from = this;
            conn3.to = readyChannel;
            this.outputConnections.Add(conn3);
            readyChannel.inputConnections.Add(conn3);
                    

        }

        public void DisconnectChannelSelector()
        {

        }

        //the cycle:
        //1. get the finished payload (from Channel Selector must be included)
        //2. update the runnable payload
        //3. send out the runnable payload
        //4. if all paylaods done, go to the destination hashtable in application
        public override void process()
        {
            if (isFirstProcess)
            {
                foreach (PayloadNode output_payload_node in plGraph.head.outputNodes)
                {
                    ParallelPayload output_payload = output_payload_node.payload;
                    output_payload.routeTag = id;
                    foreach (ParallelConnection outputConnection in outputConnections)
                    {
                        outputConnection.Flowin(output_payload);
                    }
                }
                isFirstProcess=false;
            }
            else
            {
                foreach (ParallelConnection inputConnection in inputConnections)
                {
                    ParallelPayload payload = inputConnection.Flowout();
                    if (payload != null)
                    {
                        payloadcount++;
                        ArrayList payloads = plGraph.update(payload);
                        if (payloads.Count == 0 && plGraph.isCompleted)
                        {
                            status = PROCESSORCONSTANT.STATUS_COMPLETED;
                            completedChannel.AddPayload(plGraph);
                            //destroy                             
                        }
                        else
                        {
                            foreach (ParallelPayload output_payload in payloads)
                            {
                                output_payload.routeTag = id;
                                foreach (ParallelConnection outputConnection in outputConnections)
                                {
                                    outputConnection.Flowin(output_payload);
                                }
                            }
                        }
                    }
                }
            }
        }

        public override void destroy()
        {
            if (controller != null)
            {
                controller.cycleProcessors.Remove(this);
            }
        }

        public override void PreParse()
        {
            base.PreParse();
            foreach (XmlNode child in node.ChildNodes)
            {
                if (child.Name == "PlayloadGraph")
                {
                    plGraph = new PayloadGraph();
                    plGraph.parse(child);
                }
            }
        }


               
        public override void PostParse()
        {
            //readyChannel='C1' selector='S1' completedChannel='C3'
            String readyChannelName=(String)parseParameters["readyChannel"];
            readyChannel = (ParallelChannel)application.elements[readyChannelName];

            String selectorName = (String)parseParameters["selector"];
            selector = (ParallelChannelSelector)application.elements[selectorName];

            String completedChannelName = (String)parseParameters["completedChannel"];
            completedChannel = (ParallelChannel)application.elements[completedChannelName];

            ConnectChannelSelector(readyChannel,selector,completedChannel);
        }

    }
}
